package com.zg.generator.util;

import java.io.*;
import java.net.URL;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zg.common.core.dao.generator.GenTmpl;
import com.zg.common.core.dao.generator.GenTmplDao;
import com.zg.generator.config.EngineConfig;
import freemarker.cache.StringTemplateLoader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.ClassUtils;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateExceptionHandler;
import lombok.extern.slf4j.Slf4j;

/**
 * @author Zxb
 */
@Slf4j
@Component
public class FreeMarkerUtil {

    private static GenTmplDao tmplDao;

    @Autowired
    public void setTmplDao(GenTmplDao tmplDao) {
        FreeMarkerUtil.tmplDao = tmplDao;
    }

    /**
     * 获取包名所在文件夹类路径
     *
     * @param packageName 包名
     * @return 路径
     */
    public static File getFileByPackage(String packageName) {
        ClassLoader loader = ClassUtils.getDefaultClassLoader();
        if (loader != null) {
            URL url = loader.getResource("");
            if (url != null) {
                String path = url.getPath();
                path = path + packageName.replaceAll("\\.", "/");
                return new File(path);
            }
        }
        return null;
    }

    /**
     * 获取包名所在文件夹源代码路径
     *
     * @param isVue 是否是前端代码
     * @return 源码路径
     */
    public static File getSrcFileByPackage(Boolean isVue, String subPackageName) {

        if (isVue) {
            String vueLocation = EngineConfig.vueLocation.get();
            File f = new File(vueLocation);
            return f;
        }

        ClassLoader loader = ClassUtils.getDefaultClassLoader();
        if (loader != null) {
            URL url = loader.getResource("");
            if (url != null) {
                String path = url.getPath();
                path = path.replaceAll("target/classes", "src/main/java");
                path = path + EngineConfig.packageName.get().replaceAll("\\.", "/");
                if(StrUtil.isNotBlank(subPackageName)){
                    path = path + File.separator + subPackageName.replaceAll("\\.", "/");
                }
                File f = new File(path);
                if (!f.exists()) {
                    boolean result = f.mkdirs();
                    if (!result) {
                        log.error("创建文件夹异常");
                    }
                }
                return f;
            }
        }
        return null;
    }

    /**
     * 根据名称获取模板
     *
     * @param tmpl 模板
     * @return 模板
     * @throws IOException ID异常
     */
    public static Template getDefinedTemplate(GenTmpl tmpl) throws IOException {
        Configuration cfg = new Configuration(Configuration.VERSION_2_3_30);
        StringTemplateLoader loader = new StringTemplateLoader();
        loader.putTemplate(tmpl.getCode(), tmpl.getContent());
        cfg.setTemplateLoader(loader);
        cfg.setDefaultEncoding("UTF-8");
        cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
        return cfg.getTemplate(tmpl.getCode());
    }

    public static void generate(Object data, GenTmpl tmpl, String fileName) {
        Template template;
        try {
            String tmplCode = tmpl.getCode();
            log.info("开始获取模板：" + tmplCode);
            template = FreeMarkerUtil.getDefinedTemplate(tmpl);
            log.info("成功获取模板：" + tmplCode);
            boolean isVueTmpl = tmpl.getType().equals("2");
            File folder = getSrcFileByPackage(isVueTmpl, tmpl.getSubPackage());
            if (folder == null) {
                log.info("目标文件夹不存在");
                return;
            }
            if (!folder.exists()) {
                boolean result = folder.mkdirs();
                if (!result) {
                    log.info("创建目的文件夹失败");
                    return;
                }
            }
            File file = new File(folder.getAbsolutePath() + File.separator + fileName);
            log.info("开始生产文件：" + file.getAbsolutePath());
            OutputStream os = new FileOutputStream(file);
            Writer out = new OutputStreamWriter(os);
            template.process(data, out);
            out.close();
            os.close();
            log.info("成功生产文件：" + file.getAbsolutePath());
        } catch (Exception e) {
            e.printStackTrace();
            log.error("生成过程出现异常");
        }
    }
}
